package com.springboot.cloud.sysadmin.organization.service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.springboot.cloud.common.core.exception.CustomException;
import com.springboot.cloud.common.core.utils.file.FileUtil;
import com.springboot.cloud.common.core.utils.sms.SMSUtils;
import com.springboot.cloud.sysadmin.organization.config.MyMetaObjectHandler;
import com.springboot.cloud.sysadmin.organization.dao.UserMapper;
import com.springboot.cloud.sysadmin.organization.entity.param.UserQueryParam;
import com.springboot.cloud.sysadmin.organization.entity.po.Dept;
import com.springboot.cloud.sysadmin.organization.entity.po.Position;
import com.springboot.cloud.sysadmin.organization.entity.po.Role;
import com.springboot.cloud.sysadmin.organization.entity.po.User;
import com.springboot.cloud.sysadmin.organization.entity.vo.UserVo;
import com.springboot.cloud.sysadmin.organization.exception.UserNotFoundException;
import com.springboot.cloud.sysadmin.organization.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;

/**
 * Created by ZengJian on 2021/2/3 0003 上午 9:22
 */
@Service
@Slf4j
public class UserService extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private  RoleService roleService;
    @Autowired
    private  DeptService deptService;
    @Autowired
    private  PositionService positionService;
    @Autowired
    private  UserMapper userMapper;
    @Autowired
    private  IUserDeptService userDeptService;
    @Autowired
    private  IUserPositionService userPositionService;

    @Override
    public boolean add(User user) {
        User user1 = this.getOne(new QueryWrapper<User>()
                .eq(StrUtil.isNotBlank(user.getUsername()), "username", user.getUsername())
                .or()
                .eq(StrUtil.isNotBlank(user.getMobile()), "mobile", user.getMobile()), false);
        if (ObjectUtil.isNull(user1)) {
            PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            if (StrUtil.isNotBlank(user.getPassword())) {
                user.setPassword(passwordEncoder.encode(user.getPassword()));
            } else {
                if (!SMSUtils.isMobile(user.getMobile())) {
                    return false;
                }
                if (user.getMobile().length() > 8) {
                    String pwd = user.getMobile().substring(user.getMobile().length() - 8, user.getMobile().length());
                    log.debug("pwd1:" + pwd);
                    user.setPassword(passwordEncoder.encode(pwd));
                } else {
                    DecimalFormat zeroize = new DecimalFormat("0.000000");
                    String pwd = zeroize.format(Integer.valueOf(user.getMobile())).replace(".", "").substring(0, 8);
                    log.debug("pwd2:" + pwd);
                    user.setPassword(passwordEncoder.encode(pwd));
                }
//               user.setPassword(passwordEncoder.encode("123456789"));
            }
            boolean inserts = this.saveOrUpdate(user);
            log.debug("user.getId():{}", user.getId());
            userRoleService.saveBatch(user.getId(), user.getRoles());
            userPositionService.saveBatch(user.getId(), user.getPositions());
            userDeptService.saveBatch(user.getId(), user.getDepts());
            return inserts;
        }
        return false;
    }

    @Override
//    @CacheInvalidate(name = "user::", key = "#id")
    public boolean delete(Set<String> ids) {

        log.debug("idsasdf:{}", ids);
        for (String id : ids) {
            userRoleService.removeByUserId(id);
            userPositionService.removeByUserId(id);
            userDeptService.removeByUserId(id);
        }
        return this.removeByIds(ids);
    }

    @Override
//    @CacheInvalidate(name = "user::", key = "#user.id")
    public boolean update(User user) {
        User user1 = this.getById(user.getId());
        if (ObjectUtil.isNull(user1)) {
            return false;
        }
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (StrUtil.isNotBlank(user.getPassword())) {
            user.setPassword(passwordEncoder.encode(user.getPassword()));
        }
        boolean isSuccess = this.updateById(user);
        userRoleService.saveBatch(user.getId(), user.getRoles());
        userPositionService.saveBatch(user.getId(), user.getPositions());
        userDeptService.saveBatch(user.getId(), user.getDepts());
        return isSuccess;
    }

//    UserUpdateBasicForm

    @Override
    //    @CacheInvalidate(name = "user::", key = "#user.id")
    public boolean updateBasic(User user) {
        User user1 = this.getById(user.getId());
        if (ObjectUtil.isNull(user1)) {
            return false;
        }
        boolean isSuccess = this.updateById(user);
        return isSuccess;
    }

    @Override
    public boolean updateUserPwd(User user) {
        User user1 = getByUniqueId(user.getUsername());
        if (ObjectUtil.isNull(user1)) {
            return false;
        }
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (StrUtil.isBlank(user.getPassword())) {
            return false;
        }
        user1.setPassword(passwordEncoder.encode(user.getPassword()));
        return this.updateById(user1);
    }

    @Override
    public boolean updateEnabled(User user) {
        User user1 = this.getById(user.getId());
        if (ObjectUtil.isNull(user1)) {
            return false;
        }
        return this.updateById(user);
    }

    @Override
    public boolean updateUserAvatar(User user) {
        User user1 = this.getById(user.getId());
        if (ObjectUtil.isNull(user1)) {
            return false;
        }
        return this.updateById(user);
    }

    @Override
//    @Cached(name = "user::", key = "#id", cacheType = CacheType.BOTH)
    public UserVo get(String id) {
        User user = this.getById(id);
        if (ObjectUtil.isNull(user)) {
            throw new UserNotFoundException("没有找到id为:" + id + "的用户");
        }
        user.setRoles(userRoleService.queryByUserId(id));
        Set<String> roles = new TreeSet<String>();
        for (String str : userRoleService.queryByUserId(user.getId())) {
            roles.add(roleService.getRole(str).getCode());
        }
        log.debug("roles:{}", roles);
        user.setRoles(roles);
        user.setPositions(userPositionService.queryByUserId(id));
        user.setDepts(userDeptService.queryByUserId(id));
        return new UserVo(user);
    }

    @Override
    public boolean getUser(String id) {
        User user = this.getById(id);
        if (ObjectUtil.isNull(user)) {
            return false;
        }
        return true;
    }

    @Override
    public User getByUserId(String id) {
        User user = this.getById(id);
        if (ObjectUtil.isNull(user)) {
            throw new UserNotFoundException("没有找到id为:" + id + "的用户");
        }
        user.setRoles(userRoleService.queryByUserId(id));
        Set<String> roles = new TreeSet<String>();
        for (String str : userRoleService.queryByUserId(user.getId())) {
            roles.add(roleService.getRole(str).getCode());
        }
        log.debug("roles:{}", roles);
        user.setRoles(roles);
        user.setPositions(userPositionService.queryByUserId(id));
        user.setDepts(userDeptService.queryByUserId(id));
        return user;
    }

    @Override
//    @Cached(name = "user::", key = "#uniqueId", cacheType = CacheType.BOTH)
    public User getByUniqueId(String uniqueId) {
        User user = this.getOne(new QueryWrapper<User>()
                .eq("username", uniqueId)
                .or()
                .eq("mobile", uniqueId)
                .or()
                .eq("open_id", uniqueId), false);
        if (ObjectUtil.isNull(user)) {
            throw new UserNotFoundException("没有找到uniqueId为:" + uniqueId + "的用户");
        }
        user.setRoles(userRoleService.queryByUserId(user.getId()));
        Set<String> roles = new TreeSet<String>();
        for (String str : userRoleService.queryByUserId(user.getId())) {
            roles.add(roleService.getRole(str).getCode());
        }
        log.debug("roles:{}", roles);
        user.setRoles(roles);
        user.setDepts(userDeptService.queryByUserId(user.getId()));

        user.setPositions(userPositionService.queryByUserId(user.getId()));
        return user;
    }

    @Override
//    @Cached(name = "user::", key = "#uniqueId", cacheType = CacheType.BOTH)
    public User getAllByUniqueId(String uniqueId) {
        User user = this.getOne(new QueryWrapper<User>()
                .eq("username", uniqueId)
                .or()
                .eq("mobile", uniqueId)
                .or()
                .eq("open_id", uniqueId), false);
        if (ObjectUtil.isNull(user)) {
            throw new UserNotFoundException("没有找到uniqueId为:" + uniqueId + "的用户");
        }
        Set<String> roles = userRoleService.queryByUserId(user.getId());
//        user.setRoles(userRoleService.queryByUserId(user.getId()));
//        Set<String> roles=new TreeSet<String>();
//        for(String str: userRoleService.queryByUserId(user.getId())){
//            roles.add(roleService.get(str).getCode());
//        }
//        log.debug("roles:{}",roles);
//        user.setRoles(roles);
//
        if (!roles.isEmpty()) {
            Role role = new Role();
            Set<String> roleOther = new HashSet<>();
            for (String roleId : roles) {
                role = roleService.getRole(roleId);
                roleOther.add(role.getName());
            }
            user.setRoles(roleOther);
        }
//        user.setDepts(userDeptService.queryByUserId(user.getId()));
        Set<String> depts = userDeptService.queryByUserId(user.getId());

        if (!depts.isEmpty()) {
            Dept dept = new Dept();
            Set<String> deptOther = new HashSet<>();
            for (String deptId : depts) {
                dept = deptService.getDept(deptId);
                deptOther.add(dept.getName());
            }
            user.setDepts(deptOther);
        }
        Set<String> positions = userPositionService.queryByUserId(user.getId());

        if (!positions.isEmpty()) {
            Position position = new Position();
            Set<String> positionsOther = new HashSet<>();
            for (String positionId : positions) {
                position = positionService.getPosition(positionId);
                positionsOther.add(position.getName());
            }
            user.setPositions(positionsOther);
        }

//        user.setPositions(userPositionService.queryByUserId(user.getId()));
        return user;
    }

    @Override
    public User getUserByOpenId(String openId) {
        User user = this.getOne(new QueryWrapper<User>()
                .eq("open_id", openId), false);
        if (ObjectUtil.isNull(user)) {
            throw new UserNotFoundException("没有找到openId为:" + openId + "的用户");
        }

        return user;
    }

    public User getUserByUniqueId(String uniqueId) {
        System.out.println("uniqueId:"+uniqueId);
        User user = this.getOne(new QueryWrapper<User>()
                .eq("username", uniqueId)
                .or()
                .eq("mobile", uniqueId)
                .or()
                .eq("open_id", uniqueId), false);
        if (ObjectUtil.isNull(user)) {
            throw new UserNotFoundException("没有找到uniqueId为:" + uniqueId + "的用户");
        }
        user.setRoles(userRoleService.queryByUserId(user.getId()));
        Set<String> roles = new TreeSet<String>();
        for (String str : userRoleService.queryByUserId(user.getId())) {
            roles.add(roleService.getRole(str).getCode());
        }
        log.debug("roles:{}", roles);
        user.setRoles(roles);
        user.setDepts(userDeptService.queryByUserId(user.getId()));
        user.setPositions(userPositionService.queryByUserId(user.getId()));
        return user;
    }

    @Override
//    @DataScope(deptAlias = "ud", userAlias = "u")
    public IPage<UserVo> query(Page page, UserQueryParam userQueryParam) {
        String username = getUsername();
        User user = this.getUserByUniqueId(username);
        userQueryParam.setUserId(user.getId());
        List<String> dataScope1 = new ArrayList<>();
        for (String code : user.getRoles()) {
            Role role1 = roleService.getRoleByCode(code);
            dataScope1.add(role1.getDataScope());
        }
        userQueryParam.setDataScope(dataScope1);
        log.debug("userQueryParam:", userQueryParam.getDeptId());
        IPage<User> iPageUser = userMapper.selectPageListUser(page, userQueryParam);
        return iPageUser.convert(UserVo::new);
    }

    @Override
    public List<User> listUser() {
        return this.list();
    }

    @Override
    public void download(List<User> userList, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (User user : userList) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("账号", user.getUsername());
            map.put("邮箱", user.getEmail());
            map.put("手机号码", user.getMobile());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    /**
     * 导入用户数据
     *
     * @param userList        用户数据列表
     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
     * @param operName        操作用户
     * @return 结果
     */
    @Override
    public String importUser(List<User> userList, Boolean isUpdateSupport, String operName) {
        log.debug("userList:", userList);
        log.debug("isUpdateSupport", isUpdateSupport);
        log.debug("operName", operName);
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (ArrayUtil.isEmpty(userList)) {
            throw new CustomException("导入用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
//        String password = configService.selectConfigByKey("sys.user.initPassword");
        for (User user : userList) {
            try {
                // 验证是否存在这个用户
                User u = getUserByUniqueId(user.getUsername());
                if (ObjectUtil.isNull(u)) {
                    if (StrUtil.isNotBlank(user.getPassword()))
                        user.setPassword(passwordEncoder.encode("123456789"));
                    user.setCreatedBy(operName);
                    this.add(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUsername() + " 导入成功");
                } else if (isUpdateSupport) {
                    user.setUpdatedBy(operName);
                    user.setId(getByUniqueId(operName).getId());
                    this.update(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUsername() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUsername() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + user.getUsername() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new CustomException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    public String getUsername() {
        MyMetaObjectHandler myMetaObjectHandler = new MyMetaObjectHandler();
        return myMetaObjectHandler.getCurrentUsername();
    }

    @Override
    public boolean updateOpenId(String username, String openId) {

        User user = this.getUserByUniqueId(username);
        user.setOpenId(openId);

        User user1 = this.getById(user.getId());

        if (ObjectUtil.isNull(user1)) {
            return false;
        }
        return this.updateById(user);
    }
}
